﻿using System.Linq.Expressions;
using System.Reflection;
using AntDesign.TableModels;

namespace SageKing.Blazor.OpenIdService.Helpers;

public static class DynamicCellRenderFragmentGenerator
{
    #region 表达式树
    public static Delegate GenerateDynamicRenderFragment<TT>(
        Func<CellData<TT>, string, RenderFragment> func,
        string propertyName,
        bool isEdit,
        Dictionary<string, Dictionary<string, object>> columnsByNamePropertySet)
    {
        // 1. 定义委托签名中所需的参数表达式
        ParameterExpression cellDataParam = Expression.Parameter(typeof(CellData<TT>), "cellData");

        // 2. 构建表达式体
        Expression body = BuildExpressionBody(cellDataParam, func, propertyName, isEdit, columnsByNamePropertySet);

        // 3. 构造 Lambda 表达式
        LambdaExpression lambda = Expression.Lambda(body, cellDataParam);

        // 4. 编译 Lambda 表达式为委托
        return lambda.Compile();
    }

    private static Expression BuildExpressionBody<TT>(
        ParameterExpression cellDataParam,
        Func<CellData<TT>, string, RenderFragment> func,
        string propertyName,
        bool isEdit,
        Dictionary<string, Dictionary<string, object>> columnsByNamePropertySet)
    {
        // 对应 if (!isEdit && ColumnsByNamesPropertySet.TryGetValue(propertyName, out Dictionary<string, object> configset))
        // 创建一个表示 configset 的局部变量
        ParameterExpression configsetVar = Expression.Variable(typeof(Dictionary<string, object>), "configset");

        // 获取 TryGetValue 方法的信息
        MethodInfo tryGetValueMethod = typeof(Dictionary<string, Dictionary<string, object>>).GetMethod("TryGetValue");
        // 注意：由于 ColumnsByNamesPropertySet 是外部变量，我们需要捕获它
        // 假设 columnsByNamePropertySet 是通过参数传入的，这里我们创建一个常量表达式来捕获它
        Expression columnsDict = Expression.Constant(columnsByNamePropertySet, typeof(Dictionary<string, Dictionary<string, object>>));
        Expression propertyNameConst = Expression.Constant(propertyName, typeof(string));

        // 调用 TryGetValue 方法
        MethodCallExpression tryGetValueCall = Expression.Call(
            columnsDict,
            tryGetValueMethod,
            propertyNameConst,
            configsetVar);

        // 创建 !isEdit 的条件
        Expression isEditConst = Expression.Constant(isEdit, typeof(bool));
        Expression notIsEdit = Expression.Not(isEditConst);

        // 组合条件：!isEdit && tryGetValueCall
        Expression condition = Expression.AndAlso(notIsEdit, tryGetValueCall);

        // 创建 if 语句的 True 块：{ cellData.Prop = configset; }
        Expression assignProp = Expression.Assign(
            Expression.Property(cellDataParam, "Prop"), // 假设 CellData<TT> 有一个名为 Prop 的属性
            configsetVar);

        // 创建条件语句（IfThen）
        Expression ifThen = Expression.IfThen(condition, assignProp);

        // 创建调用 func.Invoke(cellData, propertyName) 的表达式
        Expression invokeFunc = Expression.Invoke(
            Expression.Constant(func), // 捕获 func 委托
            cellDataParam,
            Expression.Constant(propertyName, typeof(string)));

        // 构建整个表达式块：包括局部变量声明、条件判断、赋值和最终的 return
        Expression block = Expression.Block(
            new[] { configsetVar }, // 声明局部变量 configset
            ifThen,
            invokeFunc); // 最后返回 func 的调用结果

        return block;
    }
    #endregion
}